/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.moravian.math;

import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Test;

/**
 *
 * @author Elliot
 */
public class Vector2DTest 
{
    
   private static class VectorAndAngle
   {
       private Vector2D vector;
       private double angle;
       
       private VectorAndAngle(Vector2D vector, double angle)
       {
           this.vector = vector;
           this.angle = angle;
       }
       
       public Vector2D getVector()
       {
           return vector;
       }
       
       public double getAngle()
       {
           return angle;
       }
   }
    
    private static final double DOUBLE_TOL = Vector2D.TOL;
    
    private static final double root3Over2 = Math.sqrt(3.0) / 2.0;
    private static final double root2Over2 = Math.sqrt(2.0) / 2.0;
    
    private static final Vector2D normalZero = new Vector2D(1.0, 0.0);
    private static final Vector2D normalPiOverSix = new Vector2D(root3Over2, .5);
    private static final Vector2D normalPiOverFour = new Vector2D(root2Over2, root2Over2);
    private static final Vector2D normalPiOverThree = new Vector2D(.5, root3Over2);
    
    private static final Vector2D normalPiOverTwo = new Vector2D(0.0, 1.0);
    private static final Vector2D normalTwoPiOverThree = new Vector2D(-.5, root3Over2);
    private static final Vector2D normalThreePiOverFour = new Vector2D(-root2Over2, root2Over2);
    private static final Vector2D normalFivePiOverSix = new Vector2D(-root3Over2, .5);
    
    private static final Vector2D normalPi = new Vector2D(-1.0, 0.0);
    private static final Vector2D normalSevenPiOverSix = new Vector2D(-root3Over2, -.5);
    private static final Vector2D normalFivePiOverFour = new Vector2D(-root2Over2, -root2Over2);
    private static final Vector2D normalFourPiOverThree = new Vector2D(-.5, -root3Over2);
    
    private static final Vector2D normalThreePiOverTwo = new Vector2D(0.0, -1.0);
    private static final Vector2D normalFivePiOverThree = new Vector2D(.5, -root3Over2);
    private static final Vector2D normalSevenPiOverFour = new Vector2D(root2Over2, -root2Over2);
    private static final Vector2D normalElevenPiOverSix = new Vector2D(root3Over2, -.5);
    
    private static final Vector2D normalTwoPi = new Vector2D(1.0, 0.0);
    
    private static final List<VectorAndAngle> unitVectors;
  
    static 
    {
        unitVectors = new ArrayList<VectorAndAngle>();
        
        unitVectors.add(new VectorAndAngle(normalZero, 0.0));
        unitVectors.add(new VectorAndAngle(normalPiOverSix, Math.PI/6.0));
        unitVectors.add(new VectorAndAngle(normalPiOverFour, Math.PI/4.0));
        unitVectors.add(new VectorAndAngle(normalPiOverThree, Math.PI/3.0));
        
        unitVectors.add(new VectorAndAngle(normalPiOverTwo, Math.PI/2.0));
        unitVectors.add(new VectorAndAngle(normalTwoPiOverThree, 2.0*Math.PI/3.0));
        unitVectors.add(new VectorAndAngle(normalThreePiOverFour, 3.0*Math.PI/4.0));
        unitVectors.add(new VectorAndAngle(normalFivePiOverSix, 5.0*Math.PI/6.0));
        
        unitVectors.add(new VectorAndAngle(normalPi, Math.PI));
        unitVectors.add(new VectorAndAngle(normalSevenPiOverSix, -5.0*Math.PI/6.0));
        unitVectors.add(new VectorAndAngle(normalFivePiOverFour,  -3.0*Math.PI/4.0));
        unitVectors.add(new VectorAndAngle(normalFourPiOverThree, -2.0*Math.PI/3.0));
        
        unitVectors.add(new VectorAndAngle(normalThreePiOverTwo, -Math.PI/2.0));
        unitVectors.add(new VectorAndAngle(normalFivePiOverThree, -Math.PI/3.0));
        unitVectors.add(new VectorAndAngle(normalSevenPiOverFour, -Math.PI/4.0));
        unitVectors.add(new VectorAndAngle(normalElevenPiOverSix,  -Math.PI/6.0));
        
        unitVectors.add(new VectorAndAngle(normalTwoPi,0.0));
        
 
    }

    @Test
    public void testSimpleVector()
    {
        Vector2D zero = new Vector2D();
        assertEquals(zero, Vector2D.zero);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        
        Vector2D v = new Vector2D(2.0, 4.1);
        assertEquals(2.0, v.getX(), DOUBLE_TOL);
        assertEquals(4.1, v.getY(), DOUBLE_TOL);
        
        Vector2D v2 = new Vector2D(v);
        assertEquals(2.0, v2.getX(), DOUBLE_TOL);
        assertEquals(4.1, v2.getY(), DOUBLE_TOL);
    }
    
    @Test 
    public void testSimpleMutators()
    {
        Vector2D v = new Vector2D(2.0, 4.1);
        assertEquals(2.0, v.getX(), DOUBLE_TOL);
        assertEquals(4.1, v.getY(), DOUBLE_TOL);
        
        v.set(1.2, 2.1);
        assertEquals(1.2, v.getX(), DOUBLE_TOL);
        assertEquals(2.1, v.getY(), DOUBLE_TOL);
        
        Vector2D v2 = new Vector2D();
        assertEquals(v2, Vector2D.zero);
        assertEquals(0.0, v2.getX(), DOUBLE_TOL);
        assertEquals(0.0, v2.getY(), DOUBLE_TOL);
        
        v.set(v2);
        assertEquals(v, Vector2D.zero);
        assertEquals(0.0, v.getX(), DOUBLE_TOL);
        assertEquals(0.0, v.getY(), DOUBLE_TOL);
    }
    
    
    @Test
    public void testMagnitude()
    {
        Vector2D v = new Vector2D(3.0, 4.0);
        assertEquals(5.0, v.magnitude(), DOUBLE_TOL);
        
        
        v.set(4.0, 3.0);
        assertEquals(5.0, v.magnitude(), DOUBLE_TOL);
        
        v.set(-4.0, 3.0);
        assertEquals(5.0, v.magnitude(), DOUBLE_TOL);
        
        v.set(-4.0,- 3.0);
        assertEquals(5.0, v.magnitude(), DOUBLE_TOL);
        
        v.set(4.0, -3.0);
        assertEquals(5.0, v.magnitude(), DOUBLE_TOL);
        
        v.set(.4, .3);
        assertEquals(.5, v.magnitude(), DOUBLE_TOL);
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            assertEquals(1.0, vecAndAng.getVector().magnitude(), DOUBLE_TOL);
        }
    }
    
    
    @Test
    public void testMagnitudeSq()
    {
        Vector2D v = new Vector2D(3.0, 4.0);
        assertEquals(25.0, v.magnitudeSq(), DOUBLE_TOL);
        
        
        v.set(4.0, 3.0);
        assertEquals(25.0, v.magnitudeSq(), DOUBLE_TOL);
        
        v.set(-4.0, 3.0);
        assertEquals(25.0, v.magnitudeSq(), DOUBLE_TOL);
        
        v.set(-4.0,- 3.0);
        assertEquals(25.0, v.magnitudeSq(), DOUBLE_TOL);
        
        v.set(4.0, -3.0);
        assertEquals(25.0, v.magnitudeSq(), DOUBLE_TOL);
        
        v.set(.4, .3);
        assertEquals(.25, v.magnitudeSq(), DOUBLE_TOL);
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            assertEquals(1.0, vecAndAng.getVector().magnitudeSq(), DOUBLE_TOL);
        }
    }
   
    
    @Test 
    public void testAngle()
    {
        Vector2D v = Vector2D.zero;
        assertEquals(0.0, v.angle(), DOUBLE_TOL);
        
     
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            assertEquals(vecAndAng.getAngle(), vecAndAng.getVector().angle(), DOUBLE_TOL);
        }
        
    }
    
    
    @Test
    public void testGetRightOrtho()
    {
        Vector2D v = Vector2D.zero;
        assertTrue(v.getRightOrtho().equals(Vector2D.zero));
        
        Vector2D curVector;
        Vector2D rightOrtho;
        int rightOrthoIndex;
        Vector2D expectedRightOrtho;
        for(int i=0; i< unitVectors.size(); i++)
        {
            curVector = unitVectors.get(i).getVector();
            rightOrtho = curVector.getRightOrtho();
            
            if(i-4 < 0)
            {
                rightOrthoIndex = (unitVectors.size()-1)+ i - 4;
            }
            else
            {
                rightOrthoIndex = i-4;
            }
            
            expectedRightOrtho = unitVectors.get(rightOrthoIndex).getVector();
            
            assertTrue(rightOrtho.equals(expectedRightOrtho));
            
            
        }
    }
    
    @Test
    public void testSetRightOrtho()
    {
        Vector2D curVector;
        int rightOrthoIndex;
        Vector2D expectedRightOrtho;
        for(int i=0; i< unitVectors.size(); i++)
        {
            curVector = new Vector2D(unitVectors.get(i).getVector());
            curVector.setRightOrtho();
            if(i-4 < 0)
            {
                rightOrthoIndex = (unitVectors.size()-1)+ i - 4;
            }
            else
            {
                rightOrthoIndex = i-4;
            }
            
            expectedRightOrtho = unitVectors.get(rightOrthoIndex).getVector();
            
            assertTrue(curVector.equals(expectedRightOrtho));
            
            
        }
        
    }
    
    
    
    @Test
    public void testGetLeftOrtho()
    {
        /*
        Vector2D v = Vector2D.zero;
        assertTrue(v.getRightOrtho().equals(Vector2D.zero));
        */
        
        Vector2D curVector;
        Vector2D leftOrtho;
        int leftOrthoIndex;
        Vector2D expectedLeftOrtho;
        for(int i=0; i< unitVectors.size(); i++)
        {
            curVector = unitVectors.get(i).getVector();
            leftOrtho = curVector.getLeftOrtho();
            
            
            leftOrthoIndex =  (i + 4)%(unitVectors.size()-1);
            
            
            expectedLeftOrtho = unitVectors.get(leftOrthoIndex).getVector();
            
            assertEquals(expectedLeftOrtho, leftOrtho);
        }
    }
    
    
    
    @Test
    public void testSetLeftOrtho()
    {
        /*
        Vector2D v = Vector2D.zero;
        assertTrue(v.getRightOrtho().equals(Vector2D.zero));
        */
        
        Vector2D curVector;
        int leftOrthoIndex;
        Vector2D expectedLeftOrtho;
        for(int i=0; i< unitVectors.size(); i++)
        {
            curVector = new Vector2D(unitVectors.get(i).getVector());
            curVector.setLeftOrtho();
            
            
            leftOrthoIndex =  (i + 4)%(unitVectors.size()-1);
            
            
            expectedLeftOrtho = unitVectors.get(leftOrthoIndex).getVector();
            
            assertEquals(expectedLeftOrtho, curVector);
        }
    }
    
    
    @Test
    public void testNormalize()
    {
        Vector2D v = new Vector2D();
        assertEquals(Vector2D.zero, v);
        v.normalize();
        assertEquals(Vector2D.zero, v);
        
        Vector2D v2 = new Vector2D(2.0, 2.0);
        v2.normalize();
        assertEquals(1.0, v2.magnitude(), DOUBLE_TOL);
        assertEquals(root2Over2, v2.getX(), DOUBLE_TOL);
        assertEquals(root2Over2, v2.getY(), DOUBLE_TOL);
        
        Vector2D v3 = new Vector2D(5.0, 0.0);
        v3.normalize();
        assertEquals(1.0, v3.magnitude(), DOUBLE_TOL);
        assertEquals(1.0, v3.getX(), DOUBLE_TOL);
        assertEquals(0, v3.getY(), DOUBLE_TOL);
    }
    
    
    @Test 
    public void testGetNormalized()
    {
        Vector2D v = new Vector2D();
        assertEquals(Vector2D.zero, v);
        Vector2D vNorm = v.getNormalized();
        assertEquals(Vector2D.zero, v);
        assertEquals(Vector2D.zero, vNorm);
        
        Vector2D v2 = new Vector2D(2.0, 2.0);
        Vector2D v2Norm = v2.getNormalized();
        assertEquals(2.0, v2.getX(), DOUBLE_TOL);
        assertEquals(2.0, v2.getY(), DOUBLE_TOL);
        assertEquals(1.0, v2Norm.magnitude(), DOUBLE_TOL);
        assertEquals(root2Over2, v2Norm.getX(), DOUBLE_TOL);
        assertEquals(root2Over2, v2Norm.getY(), DOUBLE_TOL);
        
        
        Vector2D v3 = new Vector2D(5.0, 0.0);
        Vector2D v3Norm = v3.getNormalized();
        assertEquals(5.0, v3.getX(), DOUBLE_TOL);
        assertEquals(0.0, v3.getY(), DOUBLE_TOL);
        assertEquals(1.0, v3Norm.magnitude(), DOUBLE_TOL);
        assertEquals(1.0, v3Norm.getX(), DOUBLE_TOL);
        assertEquals(0.0, v3Norm.getY(), DOUBLE_TOL);
        

    }
    
    @Test
    public void testPlus()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v = v.plus(zero);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        zero = zero.plus(v);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(1.0, zero.getX(), DOUBLE_TOL);
        assertEquals(2.0, zero.getY(), DOUBLE_TOL);
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            
            Vector2D vec2 = vec.plus(vec);
            assertEquals(vec.getX()*2.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY()*2.0, vec2.getY(), DOUBLE_TOL);
        }
    }
    
    @Test
    public void testPlusEquals()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v.plusEquals(zero);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        zero.plusEquals(v);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(1.0, zero.getX(), DOUBLE_TOL);
        assertEquals(2.0, zero.getY(), DOUBLE_TOL);
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            Vector2D vec2 = new Vector2D(vec);
            
            vec2.plusEquals(vec);
            assertEquals(vec.getX()*2.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY()*2.0, vec2.getY(), DOUBLE_TOL);
        }
    }
    
    @Test
    public void testMinus()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v = v.minus(zero);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        zero = zero.minus(v);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(-1.0, zero.getX(), DOUBLE_TOL);
        assertEquals(-2.0, zero.getY(), DOUBLE_TOL);
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            
            Vector2D vec2 = vec.minus(vec);
            assertEquals(0.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(0.0, vec2.getY(), DOUBLE_TOL);
        }
    }
    
    @Test
    public void testMinusEquals()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v.minusEquals(zero);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        zero.minusEquals(v);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        assertEquals(-1.0, zero.getX(), DOUBLE_TOL);
        assertEquals(-2.0, zero.getY(), DOUBLE_TOL);
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            Vector2D vec2 = new Vector2D(vec);
            
            vec2.minusEquals(vec);
            assertEquals(0.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(0.0, vec2.getY(), DOUBLE_TOL);
        }
    }
    
    @Test
    public void testTimes()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v = v.times(1.0);
        assertEquals(1.0, v.getX(), DOUBLE_TOL);
        assertEquals(2.0, v.getY(), DOUBLE_TOL);
        
        
        zero = zero.times(4.0);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            
            Vector2D vec2 = vec.times(4.0);
            assertEquals(vec.getX() *4.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY() * 4.0, vec2.getY(), DOUBLE_TOL);
        }
        
    }
    
    
    @Test
    public void testTimesEquals()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v.timesEquals(2.0);
        assertEquals(2.0, v.getX(), DOUBLE_TOL);
        assertEquals(4.0, v.getY(), DOUBLE_TOL);
        
        
        zero.timesEquals(4.0);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            Vector2D vec2 = new Vector2D(vec);
            
            vec2.timesEquals(4.0);
            assertEquals(vec.getX() *4.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY() * 4.0, vec2.getY(), DOUBLE_TOL);
        }
    }
    
    @Test
    public void testDivide()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v = v.divide(2.0);
        assertEquals(0.5, v.getX(), DOUBLE_TOL);
        assertEquals(1.0, v.getY(), DOUBLE_TOL);
        
      
        zero = zero.divide(4.0);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        
        try
        {
            v.divide(0.0);
            fail("Should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e)
        {
            //good
        }
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            
            Vector2D vec2 = vec.divide(4.0);
            assertEquals(vec.getX() /4.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY() / 4.0, vec2.getY(), DOUBLE_TOL);
        }
    }
    
    @Test 
    public void testDivideEquals()
    {
        Vector2D zero = new Vector2D();
        Vector2D v = new Vector2D(1.0, 2.0);
        
        v.divideEquals(2.0);
        assertEquals(0.5, v.getX(), DOUBLE_TOL);
        assertEquals(1.0, v.getY(), DOUBLE_TOL);
        
      
        zero.divideEquals(4.0);
        assertEquals(0.0, zero.getX(), DOUBLE_TOL);
        assertEquals(0.0, zero.getY(), DOUBLE_TOL);
        
        
        try
        {
            v.divideEquals(0.0);
            fail("Should have thrown IllegalArgumentException");
        }
        catch(IllegalArgumentException e)
        {
            //good
        }
        
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            Vector2D vec2 = new Vector2D(vec);
            
            vec2.divideEquals(4.0);
            assertEquals(vec.getX() /4.0, vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY() / 4.0, vec2.getY(), DOUBLE_TOL);
        }
    }
    
    
    @Test
    public void testNegate()
    {
        Vector2D curVector;
        Vector2D expectedVector;
        int expectedVectorIndex;
        for(int i=0; i<unitVectors.size(); i++)
        {
            curVector = new Vector2D(unitVectors.get(i).getVector());
            curVector.negate();
            
            expectedVectorIndex = (i+8) % (unitVectors.size()-1);
            
            expectedVector = unitVectors.get(expectedVectorIndex).getVector();
            
            assertEquals(expectedVector, curVector);
        }
    }
    
    @Test
    public void testReflectX()
    {
        Vector2D curVector;
        Vector2D expectedVector;
        int expectedVectorIndex;
        for(int i=0; i<unitVectors.size(); i++)
        {
            curVector = new Vector2D(unitVectors.get(i).getVector());
            curVector.reflectX();
            
            
            if(i<=8)
            {
                expectedVectorIndex = 8-i;
            }
            else
            {
                expectedVectorIndex = 24-i;
            }
           
            
            expectedVector = unitVectors.get(expectedVectorIndex).getVector();
            
            assertEquals(expectedVector, curVector);
        }
    }
    
    @Test
    public void testReflectY()
    {
        Vector2D curVector;
        Vector2D expectedVector;
        int expectedVectorIndex;
        for(int i=0; i<unitVectors.size(); i++)
        {
            curVector = new Vector2D(unitVectors.get(i).getVector());
            curVector.reflectY();
            
            
            expectedVectorIndex =  (unitVectors.size()-1-i);
            
            expectedVector = unitVectors.get(expectedVectorIndex).getVector();
            
            assertEquals(expectedVector, curVector);
        }
    }
    
    
    @Test 
    public void testDot()
    {
        double dot1 = normalZero.dot(normalPiOverSix);
        assertEquals(normalPiOverSix.getX(), dot1, DOUBLE_TOL);
        
        double dot2 = Vector2D.zero.dot(normalPiOverSix);
        assertEquals(0.0, dot2, DOUBLE_TOL);
        
        double dot3 = normalZero.dot(normalPiOverTwo);
        assertEquals(0.0, dot3, DOUBLE_TOL);
                
        
    }
    
    @Test
    public void testScalePlus()
    {
        Vector2D v = new Vector2D();
        v = v.scalePlus(2.0, normalElevenPiOverSix);
        assertEquals(2*normalElevenPiOverSix.getX(), v.getX(), DOUBLE_TOL);
        assertEquals(2*normalElevenPiOverSix.getY(), v.getY(), DOUBLE_TOL);
        
        Vector2D v2 = new Vector2D(1.0, 1.0);
        v2 = v2.scalePlus(2.0, Vector2D.zero);
        assertEquals(1.0, v2.getX(), DOUBLE_TOL);
        assertEquals(1.0, v2.getY(), DOUBLE_TOL);
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            Vector2D vec2 = vec.scalePlus(4.5, vec);
            
            assertEquals(vec.getX()+4.5*vec.getX(), vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY()+4.5*vec.getY(), vec2.getY(), DOUBLE_TOL);
        }
            

    }
    
    @Test
    public void testScalePlusEquals()
    {
        Vector2D v = new Vector2D();
        v.scalePlusEquals(2.0, normalElevenPiOverSix);
        assertEquals(2*normalElevenPiOverSix.getX(), v.getX(), DOUBLE_TOL);
        assertEquals(2*normalElevenPiOverSix.getY(), v.getY(), DOUBLE_TOL);
        
        Vector2D v2 = new Vector2D(1.0, 1.0);
        v2.scalePlusEquals(2.0, Vector2D.zero);
        assertEquals(1.0, v2.getX(), DOUBLE_TOL);
        assertEquals(1.0, v2.getY(), DOUBLE_TOL);
        
        for(VectorAndAngle vecAndAng: unitVectors)
        {
            Vector2D vec = new Vector2D(vecAndAng.getVector());
            Vector2D vec2 = new Vector2D(vec);
            vec2.scalePlusEquals(4.5, vec);
            
            assertEquals(vec.getX()+4.5*vec.getX(), vec2.getX(), DOUBLE_TOL);
            assertEquals(vec.getY()+4.5*vec.getY(), vec2.getY(), DOUBLE_TOL);
        }
    }
    
    @Test 
    public void testTruncate()
    {
        double max = 2.0;
        
        Vector2D v1 = new Vector2D(2.0, 0.0);
        v1.truncate(max);
        assertEquals(2.0, v1.getX(), DOUBLE_TOL);
        assertEquals(0.0, v1.getY(), DOUBLE_TOL);
        assertEquals(max, v1.magnitude(), DOUBLE_TOL);
        
        Vector2D v2 = new Vector2D(2.0, 2.0);
        v2.truncate(max);
        assertEquals(Math.sqrt(2), v2.getX(), DOUBLE_TOL);
        assertEquals(Math.sqrt(2), v2.getY(), DOUBLE_TOL);
        assertEquals(max, v2.magnitude(), DOUBLE_TOL);
        
        Vector2D v3 = new Vector2D(2.51, -3.1);
        v3.truncate(max);
        assertEquals(max, v3.magnitude(), DOUBLE_TOL);
        
        Vector2D v4 = new Vector2D(3.0, 4.0);
        v4.truncate(max);
        assertEquals(1.2, v4.getX(), DOUBLE_TOL);
        assertEquals(1.6, v4.getY(), DOUBLE_TOL);
        assertEquals(max, v4.magnitude(), DOUBLE_TOL);

    }
    
    
    //equals was tested pretty extensively in the rest of the tests
    //this is the only part that wasn't tested
    @Test 
    public void testEquals()
    {
        Vector2D v = new Vector2D();
        Point2D p = new Point2D();
        
        assertFalse(v.equals(p));
    }
    
    @Test
    public void testHashCode()
    {
        Vector2D zero = new Vector2D();
        Vector2D zero2 = new Vector2D(0.0, 0.0);
        
        assertEquals(zero.hashCode(), zero2.hashCode());
    }
    
    @Test 
    public void testToString()
    {
        Vector2D v = new Vector2D(2.0, 1.0);
        String s = "(2.0, 1.0)";
        assertEquals(s, v.toString());
    }
    
    @Test
    public void testRandomVectorFixedMagnitude()
    {
        double mag = 1.0;
        for(int i=0 ; i<1000; i++)
        {
            Vector2D v = Vector2D.randomVectorFixedMagnitude(mag);
            
            assertEquals(mag, v.magnitude(), DOUBLE_TOL);
        }
        
        mag = 2.0;
        for(int i=0 ; i<1000; i++)
        {
            Vector2D v = Vector2D.randomVectorFixedMagnitude(mag);
            
            assertEquals(mag, v.magnitude(), DOUBLE_TOL);
        }
    }
    
    @Test
    public void testRandomVectorMaxMagnitude()
    {
        double mag = 1.0;
        for(int i=0 ; i<1000; i++)
        {
            Vector2D v = Vector2D.randomVectorMaxMagnitude(mag);
            
            assertTrue(v.magnitude() < mag && v.magnitude() >=0);
            
            
        }
        
        mag = 2.0;
        for(int i=0 ; i<1000; i++)
        {
            Vector2D v = Vector2D.randomVectorMaxMagnitude(mag);
            
            assertTrue(v.magnitude() < mag && v.magnitude() >=0);
        }
    }
    
    
   
}
